
#ifndef _UTILPROD_H
#define _UTILPROD_H

#include <windows.h>
#include <time.h>
#include "license.h"
#define DCMCALLTYPE			__cdecl

#define UTIL_PROD_NAME		"Pdm"
#define UTIL_PROD_EXPIRE_14	14
#define UTIL_PROD_EXPIRE_30	30
#define UTIL_PROD_EXPIRE_45	45
#define UTIL_PROD_EXPIRE_60	60
#define UTIL_PROD_LEN		64
#define UTIL_PROD_UID		0xffffffff
#define UTIL_PROD_ACT_IDENT_LEN 8

#ifdef _IHT_RELOCATE_LICENSE
	#define UTIL_PROD_EXPIRE_VAR	UTIL_PROD_EXPIRE_14
#endif

#ifndef UTIL_PROD_EXPIRE_VAR // will be defined at build time
	#define UTIL_PROD_EXPIRE_VAR	UTIL_PROD_EXPIRE_30
#endif

struct CUTILprodinfo
	{
	unsigned short product;
	unsigned short version;
	unsigned short customer;
	unsigned long option;
	char key[UTIL_PROD_LEN];
	};

struct CUTILprodinfo2
	{
	unsigned short		product;
	unsigned short		version;
	unsigned short		customer;
	unsigned __int64	option;
	char				key[UTIL_PROD_LEN];
	};

enum EBackupType {kBackupNic = 1, kBackupDirAttr = 2, kBackupDiskid = 3, kBackupProductid = 4};

class CUTILprod
	{
public:
	CUTILprod()
		{
		m_hkRoot = 0;
		hkey = 0;
		m_pDatePfx = m_pRegionPfx = m_pLicPfx = ""; 
		m_bUseNewLicense = false;
		m_SubKey[0] = '\0';
		}
	CUTILprod(HKEY hkey, char *subkey);
	virtual ~CUTILprod();

	int				Scramble(unsigned long skey, char *sdata, void *data, unsigned long len);
	int				Scramble2(unsigned long skey, char *sdata, void *data, unsigned long len);
	int				Scramble3(unsigned long skey, char *sdata, void *data, unsigned long len);
	int				SetKey(char *key);
	int				GetRegistry(char *name, void *value, unsigned long len, unsigned long uid=UTIL_PROD_UID);
	int				SetRegistry(char *name, void *value, unsigned long len, unsigned long uid=UTIL_PROD_UID);
	time_t			GetTrialStartDate();
	long			GetTrialTimeLeft();
	void			SetTrialStartDate(time_t startDate);
	BOOL			IsExpired();
	int				OpenOemLicense(CUTILprodinfo* ip, DWORD oemId);
	int				Descramble(unsigned long skey, char *sdata, void *data, unsigned long len);
	int				Descramble2(unsigned long skey, char *sdata, void *data, unsigned long len);
	int				Descramble3(unsigned long skey, char *sdata, void *data, unsigned long len);
	unsigned short	CheckSum(char *buf, unsigned long len);
	DWORD			CheckSum2(char *buf, unsigned long len);

	static unsigned short DCMCALLTYPE ConvertVersion(char *verstr, unsigned char build);
	// method to translate from the old key to the one that removed ambiguous symbols
	static void TranslateOldKey(char  *key, char* newKeyBuf);

	// uid methods
	virtual int				GetInfo(CUTILprodinfo *ip, BOOL bRecover=TRUE);
	virtual int				GetInfo(CUTILprodinfo2 *ip, BOOL bRecover=TRUE);
	virtual int				SetInfo(CUTILprodinfo *ip);
	virtual int				SetInfo(CUTILprodinfo *ip, DWORD uid);
	virtual int				SetInfo(CUTILprodinfo2 *ip){return -1;}
	virtual int				SetInfo(CUTILprodinfo2 *ip, DWORD uid){return -1;}
	virtual int				SetBackupInfo(CUTILprodinfo *ip, DWORD uid, EBackupType type = kBackupDirAttr);
	virtual int				SetBackupInfo(CUTILprodinfo *ip, EBackupType type = kBackupDirAttr);
	virtual int				SetBackupInfo(CUTILprodinfo2 *ip, DWORD uid, EBackupType type = kBackupDirAttr);
	virtual int				SetBackupInfo(CUTILprodinfo2 *ip, EBackupType type = kBackupDirAttr);
	virtual int				SetProductidInfo(CUTILprodinfo2 *ip);
	virtual unsigned long	GetUID();
	virtual unsigned long	GetUID2();
	virtual int DCMCALLTYPE GenerateKey(CUTILprodinfo *ip, unsigned long uid);
	virtual int	DCMCALLTYPE GenerateKey(CUTILprodinfo2 *ip, unsigned long uid);
	virtual int DCMCALLTYPE GenerateInfo(CUTILprodinfo *ip, unsigned long uid);
	virtual int	DCMCALLTYPE GenerateInfo(CUTILprodinfo2 *ip, unsigned long uid);
	virtual int DCMCALLTYPE InfoToText(CUTILprodinfo *ip, char *text, unsigned long len);
	virtual int	DCMCALLTYPE InfoToText(CUTILprodinfo2 *ip, char *text, unsigned long len);
	virtual int DCMCALLTYPE TextToInfo(CUTILprodinfo *ip, unsigned long *uidp, char *text);
	virtual int DCMCALLTYPE TextToInfo(CUTILprodinfo2 *ip, unsigned long *uidp, char *text);

#ifdef _NEW_OVERLOAD
    void *operator new( size_t stAllocateBlock )
	{
		LPVOID ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stAllocateBlock);
		return ret;
	}
	void operator delete( void *pvMem )
	{
		HeapFree(GetProcessHeap(), 0, pvMem);
	}
#endif

	bool	m_bUseNewLicense;
protected:
	HKEY	hkey;
	HKEY	m_hkRoot;
	char	m_SubKey[MAX_PATH];
	char*	m_pDatePfx;
	char*	m_pRegionPfx;
	char*	m_pLicPfx;
	long	m_TrialExpireDays;
	bool	m_bUpgradable;
	bool	m_bRecoverOEM;

	// overload to allow a hard crack of the license key
	virtual bool			AllowOemRead(){return false;}
	virtual unsigned long	GetTimeUid(bool bUseDefSystemDir, bool bReferenceToStdTime = true);
	virtual unsigned long   GetTimeUid2(bool bUseDefSystemDir);
	virtual unsigned long   GetTimeUid3();

	unsigned long GetDiskUid();
	unsigned long GetNicUid();
	unsigned long GetNicUid2();
	unsigned long GetProductUid();

	static const DWORD kDefNicUid;
	};

//#ifdef USE_DCMLICENSE

class CUTILprod2 : public CUTILprod
	{
public:
	CUTILprod2() : CUTILprod() { m_bUseNewLicense = true; }
	CUTILprod2(HKEY hkey, char *subkey) : CUTILprod(hkey,subkey) { m_bUseNewLicense = true; };


	// uid methods
	virtual int				GetInfo(CUTILprodinfo *ip, BOOL bRecover=TRUE);
	virtual int				GetInfo(CUTILprodinfo2 *ip, BOOL bRecover=TRUE);
	virtual int				SetInfo(CUTILprodinfo *ip) { return -1;};
	virtual int				SetInfo(CUTILprodinfo *ip, DWORD uid) { return -1;};
	virtual int				SetInfo(CUTILprodinfo2 *ip);
	virtual int				SetInfo(CUTILprodinfo2 *ip, DWORD uid);

	virtual int				SetBackupInfo(CUTILprodinfo *ip, DWORD uid, EBackupType type = kBackupDirAttr){return CUTILprod::SetBackupInfo(ip,uid,type);};
	virtual int				SetBackupInfo(CUTILprodinfo *ip, EBackupType type = kBackupDirAttr){return CUTILprod::SetBackupInfo(ip,type);};
	virtual int				SetBackupInfo(CUTILprodinfo2 *ip, DWORD uid, EBackupType type = kBackupDirAttr){return CUTILprod::SetBackupInfo(ip,uid,type);};
	virtual int				SetBackupInfo(CUTILprodinfo2 *ip, EBackupType type = kBackupDirAttr){return CUTILprod::SetBackupInfo(ip,type);};
	virtual int				SetProductidInfo(CUTILprodinfo2 *ip){return CUTILprod::SetProductidInfo(ip);};
	virtual unsigned long	GetUID() { return CUTILprod::GetUID(); };
	virtual unsigned long	GetUID2();
	virtual int DCMCALLTYPE GenerateKey(CUTILprodinfo *ip, unsigned long uid) { return CUTILprod::GenerateKey(ip,uid); };
	virtual int	DCMCALLTYPE GenerateKey(CUTILprodinfo2 *ip, unsigned long uid) { return CUTILprod::GenerateKey(ip,uid); };
	virtual int DCMCALLTYPE GenerateInfo(CUTILprodinfo *ip, unsigned long uid);
	virtual int	DCMCALLTYPE GenerateInfo(CUTILprodinfo2 *ip, unsigned long uid) { return CUTILprod::GenerateInfo(ip,uid); };
	virtual int DCMCALLTYPE InfoToText(CUTILprodinfo *ip, char *text, unsigned long len) { return CUTILprod::InfoToText(ip,text,len); };
	virtual int	DCMCALLTYPE InfoToText(CUTILprodinfo2 *ip, char *text, unsigned long len) { return CUTILprod::InfoToText(ip,text,len); };
	virtual int DCMCALLTYPE TextToInfo(CUTILprodinfo *ip, unsigned long *uidp, char *text) { return CUTILprod::TextToInfo(ip,uidp,text); };
	virtual int DCMCALLTYPE TextToInfo(CUTILprodinfo2 *ip, unsigned long *uidp, char *text) { return CUTILprod::TextToInfo(ip,uidp,text); };

	// uid methods
	int			OpenOemLicense(CUTILprodinfo* ip, DWORD oemId) {return CUTILprod::OpenOemLicense(ip,oemId);};
	int			OpenOemLicense(CUTILprodinfo2* ip, DWORD oemId);
	};

// class for app level licenses, no common license
class CUTILprod2App : public CUTILprod2
{
public:
	CUTILprod2App() : CUTILprod2(){}
	CUTILprod2App(HKEY hkey, char *subkey) : CUTILprod2(hkey,subkey){}

	// always OR the bits with the generic so that WP has the same
	// level of capability as non-ivi apps using ivi filters
	virtual int	GetInfo(CUTILprodinfo *ip, BOOL bRecover=TRUE)
		{
		int ret = CUTILprod2::GetInfo(ip, bRecover);
//		if(ret == 0)
//			ip->option |= ((DWORD) (GetCommonOpts()) & (kLicAudDecAC3|kLicFilterVidDec));
		return ret;
		}

	virtual int	GetInfo(CUTILprodinfo2 *ip, BOOL bRecover=TRUE)
		{
		int ret = CUTILprod2::GetInfo(ip, bRecover);
//		if(ret == 0)
//			ip->option |= (GetCommonOpts() & (kLicAudDecAC3|kLicFilterVidDec));

		return ret;
		}

	UINT64 GetCommonOpts();
};
//#endif


// short-term assignment of registry letters for licensing
#define UTIL_APPEXPIRE_NAME			"_AE"
//				Date	License      Region

//  Generic		A           Z
//  Generic2	M           A
// Wintube		WT			TW

class CUTILprodGeneric : public CUTILprod
{
public:
	CUTILprodGeneric(HKEY hkey, char *subkey): CUTILprod(hkey, subkey)
	{
		m_pDatePfx = "A";
		m_pLicPfx = "Z";
        m_TrialExpireDays = UTIL_PROD_EXPIRE_VAR;
		m_bUseNewLicense = false;
	}
	virtual unsigned long GetUID()
	{
		return GetUID2();
	}
	virtual bool AllowOemRead(){return true;}
};

class CUTILprodGeneric2 : public CUTILprod2
{
public:
	CUTILprodGeneric2(HKEY hkey, char *subkey): CUTILprod2(hkey, subkey)
	{
		m_pDatePfx = "A2";
		m_pLicPfx = "Z2";
        m_TrialExpireDays = UTIL_PROD_EXPIRE_VAR;
		m_bUseNewLicense = true;
		m_bRecoverOEM = true;
	}
	virtual unsigned long GetUID()
	{
		return GetUID2();
	}
	virtual bool AllowOemRead(){return true;}
	virtual int	GetInfo (CUTILprodinfo2 *ip, BOOL bRecover=TRUE)
	{
		int ret1 = CUTILprod2::GetInfo(ip, bRecover);
		if(ret1!=0)
			ip->option = 0;

		// always OR the 32-bits old Generic license
		CUTILprodinfo inf1;
		CUTILprodGeneric prod1(m_hkRoot, m_SubKey);
		int ret2 = prod1.GetInfo(&inf1, bRecover);
		if(ret2==0)
			ip->option |= (inf1.option);

		return (ret1==0 || ret2==0) ? 0 : -1;
	}

	virtual int	SetInfo(CUTILprodinfo2 *ip)
	{
		int ret = CUTILprod2::SetInfo(ip);
		if(ret==0)
		{
			CUTILprodinfo inf1;
			CUTILprodGeneric prod1(m_hkRoot, m_SubKey);
			inf1.customer = ip->customer;
			inf1.option = (DWORD) ip->option;
			inf1.product = ip->product;
			inf1.version = ip->version;
			ret = prod1.SetInfo(&inf1);
		}
		return ret;
	}
	virtual int SetInfo(CUTILprodinfo2 *ip, DWORD uid) 
	{
		int ret = CUTILprod2::SetInfo(ip, uid); 
		if(ret==0)
		{
			CUTILprodinfo inf1;
			CUTILprodGeneric prod1(m_hkRoot, m_SubKey);
			inf1.customer = ip->customer;
			inf1.option = (DWORD) ip->option;
			inf1.product = ip->product;
			inf1.version = ip->version;
			ret = prod1.SetInfo(&inf1);
		}
		return ret;
	};


};

class CUTILProdWintube : public CUTILprod2App
{
public:
	CUTILProdWintube(HKEY hkey, char *subkey): CUTILprod2App(hkey, subkey)
	{
		m_pDatePfx = ("WT");
		m_pLicPfx = ("TW");
        m_TrialExpireDays = UTIL_PROD_EXPIRE_VAR;
		m_bUpgradable = false;
		m_bUseNewLicense = true;
		m_bRecoverOEM = true;
	}
	virtual unsigned long GetUID()
	{
		return GetUID2();
	}
};

#endif /* _UTILPROD_H */

